﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace DotNetExtensions.Core
{
    public class ValueCollection<T> : ICollection<T> where T : class
    {
        public ValueCollection()
        {

        }
        public ValueCollection(List<T> values)
        {
            if (values != null) this.Values = values;
        }
        protected readonly List<T> Values = new List<T>();
        public int Count => Values.Count;
        public bool IsReadOnly => false;

        public T this[int i]
        {
            get { return Values[i]; }
            set { Values[i] = value; }
        }

        public virtual void Add(T item)
        {
            Values.Add(item);
        }
        public virtual void Add(T item, Func<T, bool> where)
        {
            T oldest = Values.FirstOrDefault(where);
            if (oldest == null)
                Values.Add(item);
            else
            {
                int index = Values.IndexOf(oldest);
                Values[index] = item;
            }
        }
        public virtual bool TryGet(Func<T, bool> where, out T value)
        {
            value = Values.FirstOrDefault(where);
            return value != null;
        }

        public void Clear()
        {
            Values.Clear();
        }

        public bool Contains(T item)
        {
            return Values.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            Values.CopyTo(array, arrayIndex);
        }

        public IEnumerator<T> GetEnumerator()
        {
            return Values.GetEnumerator();
        }

        public bool Remove(T item)
        {
            return Values.Remove(item);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return Values.GetEnumerator();
        }

        public virtual void Parse(string json)
        {
            JToken token = JToken.Parse(json);
            if (token.Type == JTokenType.Array)
            {
                JArray array = (token as JArray);
                foreach (JToken item in array)
                {
                    Add(item.ToObject<T>());
                }
            }
            else if (token.Type == JTokenType.Object)
            {
                Add(token.ToObject<T>());
            }
        }
    }
    public class KeyValueCollection : ValueCollection<KeyValue>
    {
        public KeyValueCollection() : base()
        {

        }
        public KeyValueCollection(List<KeyValue> values) : base(values)
        {

        }
        public override void Add(KeyValue item)
        {
            base.Add(item, x => x.Name == item.Name);
        }

        public void Add(string name, string value)
        {
            Add(new KeyValue(name, value));
        }

        public string ToJson()
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            foreach (var item in this)
            {
                values.Add(item.Name, item.Value);
            }
            return JsonConvert.SerializeObject(values);
        }

        public override void Parse(string json)
        {
            JToken token = JToken.Parse(json);
            if (token.Type == JTokenType.Array)
            {
                JArray array = (token as JArray);
                foreach (JToken item in array)
                {
                    Add(item.ToObject<KeyValue>());
                }
            }
            else if (token.Type == JTokenType.Object)
            {
                Add(token.ToObject<KeyValue>());
            }
        }
    }

    public class KeyValue
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public string Path { get; set; }
        public string Domain { get; set; }

        public bool IsEmpty()
        {
            return string.IsNullOrEmpty(Name) || string.IsNullOrEmpty(Value);
        }

        public KeyValue()
        {

        }

        public KeyValue(string name, string value)
        {
            Name = name;
            Value = value;
        }
        public KeyValue(string name, string value, string path)
        {
            Name = name;
            Value = value;
            Path = path;
        }

        public KeyValue(string name, string value, string path, string domain)
        {
            Name = name;
            Value = value;
            Path = path;
            Domain = domain;
        }
    }

    public class MultipartFormDataItem
    {
        public string Name { get; set; }
        public object Value { get; set; }
        public MultipartFormDataType Type { get; set; }
        public string FileName { get; set; }
    }

    public enum MultipartFormDataType
    {
        Text = 1,
        Stream = 2
    }
}
